package com.ruoyi.generator.service;

import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.bean.BeanValidators;
import com.ruoyi.generator.entity.*;
import com.ruoyi.generator.entity.dto.EditInvoice;
import com.ruoyi.generator.mapper.ContractMapper;
import com.ruoyi.generator.mapper.InvoiceFormMapper;
import com.ruoyi.generator.util.jisuanTool;
import lombok.var;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.validation.Validator;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDate;
import java.time.YearMonth;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.time.temporal.Temporal;
import java.util.*;

/**
 * 业务字段 服务层实现
 *
 * @author ruoyi
 */
@Service
public class ContractServiceImpl implements ContractService {

    private static final Logger log = LoggerFactory.getLogger(CustomerServiceImpl.class);
    @Autowired
    private ContractMapper ContractMapper;
    @Autowired
    private InvoiceFormMapper invoiceFormMapper;
    @Autowired
    protected Validator validator;

    @Autowired
    private com.ruoyi.generator.service.CustomerService CustomerService;

    /**
     * 新增业务字段
     *
     * @param Contract 业务字段信息
     * @return 结果
     */
    @Override
    public int insertContract(Contract Contract) {
        int contractPeriod = 0;//合同周期
        int yearEndPeriod = 0;//本年运维周期
        String YearReceivedPayment = "0";//本年已回款
        String YearAgreedPayment = "0";//本年约定回款
        // 共有的参数设置

        // 获取当前年份
        int currentYear = Calendar.getInstance().get(Calendar.YEAR);
        int currentMonth = Calendar.getInstance().get(Calendar.MONTH);
        // 查询当前表的最大ID
        Long maxId = ContractMapper.getMaxId();
        Long nextId = null;
        // 计算下一个ID
        if ("捆绑合同".equals(Contract.getContractCategory())){
            nextId = Contract.getNextId(); // 如果没有最大ID，则从1开始
        }else {
            nextId = (maxId != null) ? maxId + 1 : 1; // 如果没有最大ID，则从1开始
        }

        String ContractSuffix = "";
        if (Contract.getContractType().equals("在线运维") || Contract.getContractType().equals("污水运维")) {
            ContractSuffix = "YW";
        } else if (Contract.getContractType().equals("在线建设") || Contract.getContractType().equals("污水建设")) {
            ContractSuffix = "JS";
        } else if (Contract.getContractType().equals("污水宝马") || Contract.getContractType().equals("在线宝马")) {
            ContractSuffix = "BM";
        } else if (Contract.getContractType().equals("其他")) {
            ContractSuffix = "QT";
        }
        // 生成合同编号
        String contractCode = "";
//        String contractCode = String.format("%s-%s-%d%04d",
//                currentYear,
//                nextId,
//                Contract.getContractPrefix(),
//                ContractSuffix);
        if ("补充合同".equals(Contract.getContractCategory())){
            List<String> MaxIds = ContractMapper.getMaxIdOfSupply(Contract.getContractCode());
            System.out.println(MaxIds.size());
            if (MaxIds.isEmpty()) {
                return 405;
            }else{
                contractCode = Contract.getContractCode() +"-" + MaxIds.size();
            }
        }else {
            contractCode = String.format("%s-%s-%d%04d",
                    Contract.getContractPrefix(),
                    ContractSuffix,
                    currentYear,
                    nextId);
        }
        // 设置合同编号
        if(Contract.getFormType()!=null){//判断是否为上传合同
            if("upload".equals(Contract.getFormType())){//上传合同
                Contract.setContractCode(Contract.getContractCode().trim());
                //拆分出合同编号中的前缀
                String[] parts = Contract.getContractCode().split("-");
                Contract.setContractPrefix(parts[0]);
                Contract.setContractSuffix(parts[1]);
            }
        }else {//新增合同
            Contract.setContractCode(contractCode);
            Contract.setFormType("add");
        }

        Contract.setYear(String.valueOf(currentYear));

        // 设置创建时间和创建人
        Contract.setCreateBy(SecurityUtils.getUsername());
        Contract.setManager(Contract.getManager());
        if(Contract.getContractType().equals("污水宝马")||Contract.getContractType().equals("在线宝马")||Contract.getContractType().equals("污水建设")||Contract.getContractType().equals("在线建设")){
            //当类型为 上面的 类型之一的时候不需要计算 运维周期
            Contract.setMonthOutputValue("0");
            Contract.setYearOutputValue("0");
            Contract.setStartWorkContractPeriod(0);
            Contract.setYearEndPeriod(0);
            Contract.setContractPeriod(0);
            Contract.setYearReceivedPayment(YearReceivedPayment);
            Contract.setYearAgreedPayment(YearAgreedPayment);
            Contract.setGrandTotalValue("0");
            Contract.setUnfinishedOutput(String.valueOf(Contract.getEffectiveAmount()));
            PaymentMsg paymentMsg = new PaymentMsg();
            paymentMsg.setContractCode(contractCode);
            paymentMsg.setContractAmount(String.valueOf(Contract.getEffectiveAmount()));
            paymentMsg.setPaymentType(Contract.getPaymentType());
            paymentMsg.setAgreedPayment("0");
            paymentMsg.setActualPayment("0");
            paymentMsg.setCreatedAt(new Date());

            if(Contract.getFormType()!=null){//判断是否为上传合同
                if("upload".equals(Contract.getFormType())){//上传合同
                    System.out.println("合同编号为：" + Contract.getContractCode() +"是上传合同不需要增加");
                }else {//新增合同
                    ContractMapper.insertPayMsg(paymentMsg);
                }
            }

        }else {  // 包含 在线运维 与 污水运维
            //运维周期运算
            contractPeriod= (int) jisuanTool.calculateMonthsBetweenDates(Contract.getStartDate(), Contract.getEndDate(), false);
            //运维周期
            Contract.setContractPeriod(contractPeriod);
            System.out.println("合同周期为：" + contractPeriod);
            //开工运维周期
            int startWorkContractPeriod = jisuanTool.calculateOperationPeriod(Contract.getStartDate());
            Contract.setStartWorkContractPeriod(startWorkContractPeriod);
            System.out.println("开工运维周期：" + startWorkContractPeriod);
            //本年运维周期
            yearEndPeriod = jisuanTool.calculateElapsedMonthsThisYear(Contract.getStartDate(), Contract.getEndDate());
            System.out.println("本年运维周期为：" + yearEndPeriod);
            Contract.setYearEndPeriod(yearEndPeriod);

            double monthoutvalue = Contract.getEffectiveAmount() / contractPeriod;
            // 设置月均产值，保留两位小数
            BigDecimal bdMonth = BigDecimal.valueOf(monthoutvalue).setScale(2, RoundingMode.HALF_UP);
            Contract.setMonthOutputValue(bdMonth.toString());
            // 设置本年度产值，使用 bdMonth 和 yearEndPeriod 计算
            BigDecimal yearoutvalue = bdMonth.multiply(BigDecimal.valueOf(yearEndPeriod)).setScale(2, RoundingMode.HALF_UP);
            Contract.setYearOutputValue(yearoutvalue.toString());
            //设置本年约定回款
            //调用计算约定回款方法
            BigDecimal yearAgreedPayment  =jisuanTool.calculateYearAgreedPayment(Contract.getEffectiveAmount(),Contract.getPaymentType(),Contract.getStartDate());

            Contract.setYearAgreedPayment(String.valueOf(yearAgreedPayment));
            //设置本年度已回款 默认为0
            Contract.setYearReceivedPayment(YearReceivedPayment);

            Contract.setYearOutputValue(String.valueOf(yearoutvalue));
            //signDate 获取差值月份
//            int signDate = jisuanTool.getMonth(Contract.getStartDate());
            //开工完成产值
            BigDecimal grandTotalValue = bdMonth.multiply(BigDecimal.valueOf(startWorkContractPeriod)).setScale(2, RoundingMode.HALF_UP);
            Contract.setGrandTotalValue(grandTotalValue.toString());
            //未完成产值
            BigDecimal effectiveAmount = BigDecimal.valueOf(Contract.getEffectiveAmount());
            BigDecimal unfinishedOutput = effectiveAmount.subtract(grandTotalValue).setScale(2, RoundingMode.HALF_UP);
            Contract.setUnfinishedOutput(unfinishedOutput.toString());
            //根据合同开始日期和结束日期中间的差值计算月份
            Date startDate = Contract.getStartDate();
            Date endDate = Contract.getEndDate();
            //首次回款月份
            String firstPaymentMonth=Contract.getFirstPaymentMonth();
            // 生成月份字符串数组
            List<String> monthList = generateMonthsFromContract(startDate, endDate,firstPaymentMonth);
            String countMoth = "";
                    if (Contract.getPaymentType().equals("1")) {//月结合同
                        BigDecimal totalAmount = BigDecimal.valueOf(Contract.getEffectiveAmount());
                        int periodCount = monthList.size();
                        // 计算每期标准金额（保留两位小数）
                        BigDecimal perPeriodAmount = totalAmount.divide(BigDecimal.valueOf(periodCount), 2, RoundingMode.HALF_UP);
                        // 计算前n-1期总金额
                        BigDecimal firstPartTotal = perPeriodAmount.multiply(BigDecimal.valueOf(periodCount - 1));
                        // 计算最后一期金额（包含差额补偿）
                        BigDecimal lastPeriodAmount = totalAmount.subtract(firstPartTotal);
                        
                        PaymentMsg paymentMsg = new PaymentMsg();
                        for (int i = 0; i < periodCount; i++) {
                            paymentMsg.setContractCode(Contract.getContractCode());
                            paymentMsg.setContractAmount(String.valueOf(Contract.getEffectiveAmount()));
                            paymentMsg.setPaymentType(Contract.getPaymentType());
                            paymentMsg.setCurrentMonth(monthList.get(i));
                            paymentMsg.setActualPayment("0");
                            // 最后一个月使用补偿后的金额
                            if (i == periodCount - 1) {
                                paymentMsg.setAgreedPayment(lastPeriodAmount.toString());
                            } else {
                                paymentMsg.setAgreedPayment(perPeriodAmount.toString());
                            }
                            paymentMsg.setPayment("0");
                            paymentMsg.setCreatedAt(new Date());
                            ContractMapper.insertPayMsg(paymentMsg);
                        }
                    } else if (Contract.getPaymentType().equals("2")) {//季结合同
                        BigDecimal totalAmount = BigDecimal.valueOf(Contract.getEffectiveAmount());
                        int periodCount = (int) Math.ceil(monthList.size() / 3.0);
                        // 计算每期标准金额（保留两位小数）
                        BigDecimal perPeriodAmount = totalAmount.divide(BigDecimal.valueOf(periodCount), 2, RoundingMode.HALF_UP);
                        // 计算前n-1期总金额
                        BigDecimal firstPartTotal = perPeriodAmount.multiply(BigDecimal.valueOf(periodCount - 1));
                        // 计算最后一期金额（包含差额补偿）
                        BigDecimal lastPeriodAmount = totalAmount.subtract(firstPartTotal);
                        
                        PaymentMsg paymentMsg = new PaymentMsg();
                        for (int i = 0; i < monthList.size(); i++) {
                            paymentMsg.setContractCode(Contract.getContractCode());
                            paymentMsg.setContractAmount(String.valueOf(Contract.getEffectiveAmount()));
                            paymentMsg.setPaymentType(Contract.getPaymentType());
                            paymentMsg.setCurrentMonth(monthList.get(i));
                            paymentMsg.setActualPayment("0");
                            if ((i + 1) % 3 == 0 || i == monthList.size() - 1) {
                                // 最后一期使用补偿金额
                                paymentMsg.setAgreedPayment(
                                    (i == monthList.size() - 1) ? 
                                    lastPeriodAmount.toString() : 
                                    perPeriodAmount.toString()
                                );
                            } else {
                                paymentMsg.setAgreedPayment("0");
                            }
                            paymentMsg.setPayment("0");
                            paymentMsg.setCreatedAt(new Date());
                            ContractMapper.insertPayMsg(paymentMsg);
                        }
                    } else if (Contract.getPaymentType().equals("3")) {//半年年结合同
                        BigDecimal totalAmount = BigDecimal.valueOf(Contract.getEffectiveAmount());
                        int periodCount = (int) Math.ceil(monthList.size() / 6.0);
                        // 计算每期标准金额（保留两位小数）
                        BigDecimal perPeriodAmount = totalAmount.divide(BigDecimal.valueOf(periodCount), 2, RoundingMode.HALF_UP);
                        // 计算前n-1期总金额
                        BigDecimal firstPartTotal = perPeriodAmount.multiply(BigDecimal.valueOf(periodCount - 1));
                        // 计算最后一期金额（包含差额补偿）
                        BigDecimal lastPeriodAmount = totalAmount.subtract(firstPartTotal);
                        
                        PaymentMsg paymentMsg = new PaymentMsg();
                        for (int i = 0; i < monthList.size(); i++) {
                            paymentMsg.setContractCode(Contract.getContractCode());
                            paymentMsg.setContractAmount(String.valueOf(Contract.getEffectiveAmount()));
                            paymentMsg.setPaymentType(Contract.getPaymentType());
                            paymentMsg.setCurrentMonth(monthList.get(i));
                            paymentMsg.setActualPayment("0");
                            if ((i + 1) % 6 == 0 || i == monthList.size() - 1) {
                                // 最后一期使用补偿金额
                                paymentMsg.setAgreedPayment(
                                    (i == monthList.size() - 1) ? 
                                    lastPeriodAmount.toString() : 
                                    perPeriodAmount.toString()
                                );
                            } else {
                                paymentMsg.setAgreedPayment("0");
                            }
                            paymentMsg.setPayment("0");
                            paymentMsg.setCreatedAt(new Date());
                            ContractMapper.insertPayMsg(paymentMsg);
                        }
                    } else if (Contract.getPaymentType().equals("4")) {//年结合同
                        BigDecimal totalAmount = BigDecimal.valueOf(Contract.getEffectiveAmount());
                        int periodCount = (int) Math.ceil(monthList.size() / 12.0);
                        // 计算每期标准金额（保留两位小数）
                        BigDecimal perPeriodAmount = totalAmount.divide(BigDecimal.valueOf(periodCount), 2, RoundingMode.HALF_UP);
                        // 计算前n-1期总金额
                        BigDecimal firstPartTotal = perPeriodAmount.multiply(BigDecimal.valueOf(periodCount - 1));
                        // 计算最后一期金额（包含差额补偿）
                        BigDecimal lastPeriodAmount = totalAmount.subtract(firstPartTotal);
                        
                        PaymentMsg paymentMsg = new PaymentMsg();
                        for (int i = 0; i < monthList.size(); i++) {
                            paymentMsg.setContractCode(Contract.getContractCode());
                            paymentMsg.setContractAmount(String.valueOf(Contract.getEffectiveAmount()));
                            paymentMsg.setPaymentType(Contract.getPaymentType());
                            paymentMsg.setCurrentMonth(monthList.get(i));
                            paymentMsg.setActualPayment("0");
                            if ((i + 1) % 12 == 0 || i == monthList.size() - 1) {
                                // 最后一期使用补偿金额
                                paymentMsg.setAgreedPayment(
                                    (i == monthList.size() - 1) ? 
                                    lastPeriodAmount.toString() : 
                                    perPeriodAmount.toString()
                                );
                            } else {
                                paymentMsg.setAgreedPayment("0");
                            }
                            paymentMsg.setPayment("0");
                            paymentMsg.setCreatedAt(new Date());
                            ContractMapper.insertPayMsg(paymentMsg);
                        }
                    } else if (Contract.getPaymentType().equals("5")) {//验收后结算合同
                        String AgreedPayment = String.valueOf(Contract.getEffectiveAmount());
                        // 遍历数组并输出
                        PaymentMsg paymentMsg = new PaymentMsg();
                        for (int i = 0; i < monthList.size(); i++) {
                            paymentMsg.setContractCode(Contract.getContractCode());
                            paymentMsg.setContractAmount(String.valueOf(Contract.getEffectiveAmount()));
                            paymentMsg.setPaymentType(Contract.getPaymentType());
                            if (i == monthList.size() - 1) {
                                paymentMsg.setCurrentMonth(monthList.get(i));
                            }
                            paymentMsg.setActualPayment("0");
                            if (monthList.size() == 0) {
                                paymentMsg.setAgreedPayment(AgreedPayment);
                            }

                            paymentMsg.setPayment("0");
                            paymentMsg.setCreatedAt(new Date());
                            ContractMapper.insertPayMsg(paymentMsg);
                        }
                    } else {//其他
                        BigDecimal totalAmount = BigDecimal.valueOf(Contract.getEffectiveAmount());
                        int periodCount = monthList.size();
                        // 计算每期标准金额（保留两位小数）
                        BigDecimal perPeriodAmount = totalAmount.divide(BigDecimal.valueOf(periodCount), 2, RoundingMode.HALF_UP);
                        // 计算前n-1期总金额
                        BigDecimal firstPartTotal = perPeriodAmount.multiply(BigDecimal.valueOf(periodCount - 1));
                        // 计算最后一期金额（包含差额补偿）
                        BigDecimal lastPeriodAmount = totalAmount.subtract(firstPartTotal);
                        
                        PaymentMsg paymentMsg = new PaymentMsg();
                        for (int i = 0; i < periodCount; i++) {
                            paymentMsg.setContractCode(Contract.getContractCode());
                            paymentMsg.setContractAmount(String.valueOf(Contract.getEffectiveAmount()));
                            paymentMsg.setPaymentType(Contract.getPaymentType());
                            paymentMsg.setCurrentMonth(monthList.get(i));
                            paymentMsg.setActualPayment("0");
                            // 最后一个月使用补偿后的金额
                            if (i == periodCount - 1) {
                                paymentMsg.setAgreedPayment(lastPeriodAmount.toString());
                            } else {
                                paymentMsg.setAgreedPayment(perPeriodAmount.toString());
                            }
                            paymentMsg.setPayment("0");
                            paymentMsg.setCreatedAt(new Date());
                            ContractMapper.insertPayMsg(paymentMsg);
                        }
                    }
                }










        return ContractMapper.insertContract(Contract);
    }


    @Override
    public List<Contract> selectContractList(ContractSearchCriteria ContractSearchCriteria) {

        return ContractMapper.selectContractList(ContractSearchCriteria);
    }


    @Override
    public void deleteContractBycontractCode(String contractCode) {
        // 根据customerCode删除客户信息
        Contract contract = ContractMapper.selectContractByCode(contractCode);
        if (contract != null) {
            contract.setDelFlag("1"); // 1表示已删除
            // 设置更新时间和更新人
            contract.setUpdateTime(new Date());
            //登录用户中获取
            contract.setUpdateBy(SecurityUtils.getUsername());
            ContractMapper.updateContractByCode(contract);
        }
    }

    @Override
    public List<Customer> selectClientlist() {
        return ContractMapper.selectClientlist();
    }

    @Override
    public int addReturnValue(StReturnValue stReturnValue ) {
        // 确定当前时间的月份
        // 获取当前日期
        LocalDate currentDate = LocalDate.now();
        // 定义日期格式化器，格式为 YYYY-MM
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM");
        // 格式化当前月份
        String currentMonth = currentDate.format(formatter);
        Contract contract = ContractMapper.selectContractByCode(stReturnValue.getContractCode());

        // 调用新方法检查当前月份是否在集合中

            List<PaymentMsg> paymentMsgList = ContractMapper.selectPaymentMsgByContractCode(stReturnValue.getContractCode());
            if(paymentMsgList.size()>1){
                if (paymentMsgList.get(0).getCurrentMonth() != null){
                    if (!isCurrentMonthValid(paymentMsgList, currentMonth)) {
                        return 4; // 当前月份不在集合中，返回错误码
                    }
                }
            }

        EditInvoice editInvoice = stReturnValue.getEditInvoice(); //获取到的修改页面的信息

        //约定回款与实际回款逻辑--------------------------------------------------------------------------------------------------------
        if (("在线建设").equals(contract.getContractType())
                || ("污水建设").equals(contract.getContractType())
                || ("在线宝马").equals(contract.getContractType())
                || ("污水宝马").equals(contract.getContractType())
                || ("其他").equals(contract.getContractType())) {  //这类的合同 非运维合同 增加回款后 实际回款和约定回款 保持一致 都是回款金额
            // 生成当前月份
            PaymentMsg paymentMsg = new PaymentMsg();
            paymentMsg.setCurrentMonth(currentMonth);
            paymentMsg.setContractCode(stReturnValue.getContractCode());
            PaymentMsg existingPaymentMsg = ContractMapper.selectContract(paymentMsg);
            if (existingPaymentMsg != null) {
                if ("add".equals(stReturnValue.getFormType())){
                    // 如果存在同一月份的合同记录，则累加金额
                    BigDecimal existingActualPayment = new BigDecimal(existingPaymentMsg.getActualPayment());
                    BigDecimal existingAgreedPayment = new BigDecimal(existingPaymentMsg.getAgreedPayment());
                    BigDecimal currentPayment = stReturnValue.getPayment();

                    BigDecimal newActualPayment = existingActualPayment.add(currentPayment);
                    BigDecimal newAgreedPayment = existingActualPayment.add(currentPayment);

                    existingPaymentMsg.setActualPayment(newActualPayment.toString());
                    existingPaymentMsg.setAgreedPayment(newAgreedPayment.toString());
                    ContractMapper.updatePayMsg(existingPaymentMsg);
                }else if ("edit".equals(stReturnValue.getFormType())){ // 在回款明细修改页面进入的新增回款

                    BigDecimal existingActualPayment = new BigDecimal(existingPaymentMsg.getActualPayment());
                    BigDecimal existingAgreedPayment = new BigDecimal(existingPaymentMsg.getAgreedPayment());

                    BigDecimal currentPayment = stReturnValue.getPayment();
                    //总数 - 旧值 + 新值
                    BigDecimal newActualPayment = existingActualPayment.subtract(editInvoice.getOldInvoiceAmount()).add(editInvoice.getInvoiceAmount());
                    BigDecimal newAgreedPayment = existingActualPayment.subtract(editInvoice.getOldInvoiceAmount()).add(editInvoice.getInvoiceAmount());
                    existingPaymentMsg.setActualPayment(newActualPayment.toString());
                    existingPaymentMsg.setAgreedPayment(newAgreedPayment.toString());
                    ContractMapper.updatePayMsg(existingPaymentMsg);
                }

            } else {

                // 如果不存在，则创建新记录  删除有关这个合同号的信息
                ContractMapper.deletePayMsg(stReturnValue.getContractCode());

                PaymentMsg newPaymentMsg = new PaymentMsg();
                newPaymentMsg.setContractAmount(String.valueOf(contract.getEffectiveAmount()));
                newPaymentMsg.setCurrentMonth(currentMonth);
                newPaymentMsg.setContractCode(stReturnValue.getContractCode());
                newPaymentMsg.setActualPayment(stReturnValue.getPayment().toString());
                newPaymentMsg.setAgreedPayment(stReturnValue.getPayment().toString());
                newPaymentMsg.setCreatedAt(new Date());
                ContractMapper.insertPayMsg(newPaymentMsg);
            }
        } else {
            PaymentMsg paymentMsg = new PaymentMsg();
            paymentMsg.setCurrentMonth(currentMonth);
            paymentMsg.setContractCode(stReturnValue.getContractCode());
            //用合同号查出所有的PaymentMsg 信息 进行对比 如果是 没有到月份就回款 则返回错误码


            PaymentMsg paymentMsgN = ContractMapper.selectContract(paymentMsg);
            if (paymentMsgN == null) { //除了运维的合同查不到约定金额
                paymentMsgN = new PaymentMsg();
                paymentMsgN.setActualPayment("0");
            }
            //查询发票信息 获取发票总可以增加回款的金额

            //通过合同号查询合同金额
            Contract contract2 = ContractMapper.selectContractByCode(stReturnValue.getContractCode());
            if (contract2 == null) {
                return 2;// 合同不存在返回错误码
            }

            double contractAmount = contract2.getEffectiveAmount();
            List<StReturnValue> returnValueList = ContractMapper.selectReturnValueByContractNumber(stReturnValue.getContractCode());
            double totalAmount = 0.0;
            for (StReturnValue returnValue : returnValueList) {
                totalAmount += Double.parseDouble(String.valueOf(returnValue.getPayment()));
            }

            if("add".equals(stReturnValue.getFormType())){ // 新增的时候验证是否超过合同金额

                double currentAmount = Double.parseDouble(String.valueOf(stReturnValue.getPayment()));
                if (totalAmount + currentAmount > contractAmount) {
                    return 3; // 已回款总额超过合同金额返回错误码
                }

            } else if ("edit".equals(stReturnValue.getFormType())) {   //修改的时候验证是否超过合同金额
                // 假设 editInvoice.getInvoiceAmount() 返回一个 BigDecimal
                BigDecimal invoiceAmount = editInvoice.getInvoiceAmount();

                // 将 BigDecimal 转换为 double
                double currentAmount = invoiceAmount.doubleValue();
                if (totalAmount + currentAmount > contractAmount) {
                    return 3; // 已回款总额超过合同金额返回错误码
                }
            }


            BigDecimal ActualPayment;
            BigDecimal returnValue = stReturnValue.getPayment();

            if ("add".equals(stReturnValue.getFormType())){ //add 的 实际回款金额修改
                if ("0".equals(paymentMsgN.getActualPayment()) ) {
                    // 如果实际回款为null或为0，则修改为回款金额
                    ActualPayment = returnValue;
                } else {
                    // 将实际回款转换为 BigDecimal
                    BigDecimal existingPayment = new BigDecimal(paymentMsgN.getActualPayment());

                    ActualPayment = existingPayment.add(returnValue); // 进行数值相加
                }
                paymentMsg.setActualPayment(String.valueOf(ActualPayment));

                ContractMapper.updatePayMsg(paymentMsg);
            } else if ("edit".equals(stReturnValue.getFormType())) { //修改的实际回款金额计算
                // 将实际回款转换为 BigDecimal
                BigDecimal existingPayment = new BigDecimal(paymentMsgN.getActualPayment()); // 总值
                BigDecimal oldInvoiceAmount = editInvoice.getOldInvoiceAmount();
                BigDecimal newInvoiceAmount = editInvoice.getInvoiceAmount();
                ActualPayment = existingPayment.subtract(oldInvoiceAmount).add(newInvoiceAmount);
                paymentMsg.setActualPayment(String.valueOf(ActualPayment));
                ContractMapper.updatePayMsg(paymentMsg);
            }


        }


        // 发票逻辑--------------------------------------------------------------------------------------------
        // 设置回款日期为当前时间
        stReturnValue.setPaymentDate(new Date());

        InvoiceForm invoiceForm = new InvoiceForm();

        if(stReturnValue.getHasInvoice().equals("1") && !"upload".equals(stReturnValue.getFormType())){//有发票的路径
            //修改发票信息的数据库状态
            invoiceForm.setId(stReturnValue.getInvoiceId());
            String availableAmount =invoiceFormMapper.queryAvailableAmountByInvoiceId(stReturnValue.getInvoiceId());
            Double availableAmountNew = new Double(availableAmount);
            //判断一下可开发票金额小于等于0了就返回错误码
            if("add".equals(stReturnValue.getFormType())){
                availableAmountNew=Double.valueOf(availableAmount)-Double.valueOf(String.valueOf(stReturnValue.getPayment()));
                if(availableAmountNew<0){
                    return 5; // 已开发票总额超过合同金额返回错误码
                }
            }else if ("edit".equals(stReturnValue.getFormType())){
                availableAmountNew = Double.valueOf(availableAmount) + Double.valueOf(String.valueOf(editInvoice.getOldInvoiceAmount())) - Double.valueOf(String.valueOf(editInvoice.getInvoiceAmount()));
                if(availableAmountNew<0){
                    return 5; // 已开发票总额超过合同金额返回错误码
                }
            }

            invoiceForm.setAvailableAmount(String.valueOf(availableAmountNew));
            //如果发票回款金额已经没有了可以添加回款并且修改成已回款
            if(Double.valueOf(availableAmountNew)==0){
                invoiceForm.setPaymentStatus("已回款");
            }else if(Double.valueOf(availableAmountNew)>0){
                invoiceForm.setPaymentStatus("未回款");
            }

            invoiceFormMapper.updateInvoiceForm(invoiceForm);
        }else{//无发票的路径

            if( "add".equals(stReturnValue.getFormType())){ //新增的时候添加发票信息
                invoiceForm.setContractNumber(stReturnValue.getContractCode());
                invoiceForm.setPaymentStatus("待开票已回款");
                invoiceForm.setInvoiceAmount(Double.valueOf(String.valueOf(stReturnValue.getPayment())));
                invoiceForm.setRemark("未开票");
                invoiceFormMapper.insertInvoiceForm(invoiceForm);
            }else if ( "edit".equals(stReturnValue.getFormType())){ //修改的时候修改发票信息
                invoiceForm.setId(editInvoice.getInvoiceId());
                BigDecimal a =editInvoice.getInvoiceAmount();
                invoiceForm.setInvoiceAmount(a.doubleValue());
                invoiceFormMapper.updateInvoiceForm(invoiceForm);
            }else if ("upload".equals(stReturnValue.getFormType())){//上传的时候
                System.out.println("上传");
            }

        }
        //修改合同中的关于bm，qt，js 类型的 合同的 月产值 年产值和未完成产值

        if (("在线建设").equals(contract.getContractType())
                || ("污水建设").equals(contract.getContractType())
                || ("在线宝马").equals(contract.getContractType())
                || ("污水宝马").equals(contract.getContractType())
                || ("其他").equals(contract.getContractType())) {
            //月产值
            try {
                if (("0").equals(contract.getMonthOutputValue())) { // 第一次回款，金额就是开票金额
                    contract.setMonthOutputValue(String.valueOf(stReturnValue.getPayment()));
                } else if (contract.getMonthOutputValue() != null
                        && !contract.getMonthOutputValue().isEmpty()
                        && Double.parseDouble(contract.getMonthOutputValue()) > 0) { // 有值并且大于零，那么直接相加
                    if ( "add".equals(stReturnValue.getFormType())){//新增回款的时候
                        BigDecimal currentValue = new BigDecimal(contract.getMonthOutputValue());
                        BigDecimal paymentValue = stReturnValue.getPayment();
                        if (paymentValue != null) {
                            BigDecimal sum = currentValue.add(paymentValue);
                            // 保留2位小数
                            contract.setMonthOutputValue(sum.setScale(2, RoundingMode.HALF_UP).toString());
                        }
                    }else if ( "edit".equals(stReturnValue.getFormType())){//修改回款的时候
                        BigDecimal currentValue = new BigDecimal(contract.getMonthOutputValue());
                        BigDecimal paymentValue = editInvoice.getInvoiceAmount();
                        if (paymentValue != null) {
                            BigDecimal sum = currentValue.subtract(editInvoice.getOldInvoiceAmount()).add(paymentValue);
                            // 保留2位小数
                            contract.setYearOutputValue(sum.setScale(2, RoundingMode.HALF_UP).toString());
                        }

                    }
                }
            } catch (NumberFormatException e) {
                // 处理金额格式异常
                e.printStackTrace();
            }
            //年产值
            if (("0").equals(contract.getYearOutputValue())) { // 第一次回款，金额就是开票金额
                contract.setYearOutputValue(String.valueOf(stReturnValue.getPayment()));
            } else if (contract.getYearOutputValue() != null
                    && !contract.getYearOutputValue().isEmpty()
                    && Double.parseDouble(contract.getYearOutputValue()) > 0) {// 有值并且大于零，那么直接相加
                if("add".equals(stReturnValue.getFormType())){//新增回款的时候
                    BigDecimal currentValue = new BigDecimal(contract.getYearOutputValue());
                    BigDecimal paymentValue = stReturnValue.getPayment();
                    if (paymentValue != null) {
                        BigDecimal sum = currentValue.add(paymentValue);
                        // 保留2位小数
                        contract.setYearOutputValue(sum.setScale(2, RoundingMode.HALF_UP).toString());
                    }
                }else if( "edit".equals(stReturnValue)){ //修改回款的时候
                    BigDecimal currentValue = new BigDecimal(contract.getYearOutputValue());
                    BigDecimal paymentValue = editInvoice.getInvoiceAmount();
                    if (paymentValue != null) {
                        BigDecimal sum = currentValue.subtract(editInvoice.getOldInvoiceAmount()).add(paymentValue);
                        // 保留2位小数
                        contract.setYearOutputValue(sum.setScale(2, RoundingMode.HALF_UP).toString());
                    }
                }

            }

            //未完成产值
            if ( "add".equals(stReturnValue.getFormType())){ //新增回款
                // 获取未完成金额，计算逻辑
                BigDecimal unfinishedOutput = new BigDecimal(contract.getUnfinishedOutput());
                BigDecimal payment = stReturnValue.getPayment(); // 确保此处返回的是 BigDecimal 类型
                // 计算未完成金额
                BigDecimal result = unfinishedOutput.subtract(payment); // 进行减法
                // 保留2位小数
                contract.setUnfinishedOutput(result.setScale(2, RoundingMode.HALF_UP).toString());
            }else if ( "edit".equals(stReturnValue.getFormType())){//修改回款
                // 获取未完成金额，计算逻辑
                BigDecimal unfinishedOutput = new BigDecimal(contract.getUnfinishedOutput());
                BigDecimal payment = editInvoice.getInvoiceAmount();
                // 计算未完成金额
                BigDecimal result = unfinishedOutput.add(editInvoice.getOldInvoiceAmount()).subtract(payment); // 进行减法
                // 保留2位小数
                contract.setUnfinishedOutput(result.setScale(2, RoundingMode.HALF_UP).toString());
            }


            //计算本年已回款--------------
            String yearReceivedPayment = "0";
            if ( "add".equals(stReturnValue.getFormType())){ //新增回款的时候
                if(contract.getYearReceivedPayment()!=null){//表示已经有过回款
                    // 将字符串转换为数值类型（假设是整数）
                    int currentPayment = Integer.parseInt(contract.getYearReceivedPayment());
                    int newPayment = Integer.parseInt(String.valueOf(stReturnValue.getPayment()));
                    // 相加并转回字符串
                    yearReceivedPayment = String.valueOf(currentPayment + newPayment);
                }
            }else if ( "edit".equals(stReturnValue.getFormType())){ //修改回款的时候
                if(contract.getYearReceivedPayment()!=null){//表示已经有过回款
                    // 将字符串转换为数值类型（假设是整数）
                    double currentPayment = Double.parseDouble(contract.getYearReceivedPayment());
                    BigDecimal newPayment = editInvoice.getInvoiceAmount();
                    BigDecimal  oldpayment = editInvoice.getOldInvoiceAmount();
                    // 相加并转回字符串
                    yearReceivedPayment = String.valueOf(currentPayment - oldpayment.doubleValue() + newPayment.doubleValue());
                }
            }
            contract.setYearReceivedPayment(yearReceivedPayment);


            //设置开工完成产值 ------------------------------ 保持代码在方法最下面 不用修改  关于 修改回款 还是   新增回款------------------------------------
            if (("在线建设").equals(contract.getContractType())
                    || ("污水建设").equals(contract.getContractType())
                    || ("在线宝马").equals(contract.getContractType())
                    || ("污水宝马").equals(contract.getContractType())
                    || ("其他").equals(contract.getContractType())) {
                //查询出所有的回款的金额相加
                List<StReturnValue> returnValues = ContractMapper.queryReturnValue(contract.getContractCode());
                String totalPayment = calculateTotalPayment(returnValues);
                if (totalPayment .equals("0")) {
                    totalPayment = String.valueOf(stReturnValue.getPayment());
                }else {
                    totalPayment = String.valueOf(new BigDecimal(totalPayment).add(stReturnValue.getPayment()));
                }
                contract.setGrandTotalValue(totalPayment);
            }
            ContractMapper.updateContractByCode(contract);

        } else {
            System.out.println("合同类别：" + contract.getContractType() + "的在新增回款的时候不修改");
        }

        //ReturnvalHistory 的计算
        ReturnvalHistory returnvalHistory = ContractMapper.selectReturnvalHistoryByContractCode(stReturnValue.getContractCode());
        //判断如果查到值则表示 新增过，没有的话就是没有新增过回款 则增加这个合同在这个表中的值
        if (returnvalHistory != null) {
            returnvalHistory.setContractCode(stReturnValue.getContractCode());
            //根据returnvalHistory中的2025的值在加上当前的stReturnValue.getPayment())
            returnvalHistory.setYear2025Payment(String.valueOf(new BigDecimal(returnvalHistory.getYear2025Payment()).add(stReturnValue.getPayment())));
            ContractMapper.updateReturnvalHistoryByContractCode(returnvalHistory);
        } else {
            returnvalHistory = new ReturnvalHistory();
            returnvalHistory.setContractCode(stReturnValue.getContractCode());
            returnvalHistory.setYear2025Payment(String.valueOf(stReturnValue.getPayment()));
            ContractMapper.addReturnValueHistory(returnvalHistory);
        }


        //写一个方法 传入 当前年份 判断是符合哪个属性  





        stReturnValue.setPaymentDate(new Date());
        //回款月份取当前月份 例如2023年9月，则取9月
        stReturnValue.setPaymentMonth(String.valueOf(Calendar.getInstance().get(Calendar.MONTH) + 1) +  "月");
        if ( "add".equals(stReturnValue.getFormType())) {
            return ContractMapper.addReturnValue(stReturnValue);
        }else  if ( "upload".equals(stReturnValue.getFormType())) {
            return ContractMapper.addReturnValue(stReturnValue);
        }
        else {//修改回款的时候修改回款金额
            stReturnValue.setPayment(editInvoice.getInvoiceAmount());
            stReturnValue.setId(Long.valueOf(editInvoice.getReturnValueId()));
            return ContractMapper.editReturnValue(stReturnValue);
        }
    }

    /**
     * 计算 List<StReturnValue> 中所有 payment 的总和
     *
     * @param returnValueList StReturnValue 列表
     * @return 所有 payment 的总和，返回值为 String 类型
     */
    public String calculateTotalPayment(List<StReturnValue> returnValueList) {
        BigDecimal totalPayment = BigDecimal.ZERO;
        if (returnValueList.size() == 0 || returnValueList == null){
            return "0";
        }
        for (StReturnValue returnValue : returnValueList) {
            BigDecimal payment = returnValue.getPayment();
            if (payment != null) {
                totalPayment = totalPayment.add(payment);
            }
        }
        return totalPayment.toString();
    }

    @Override
    public List<String> queryContractNumberByLike(String queryString) {
        return ContractMapper.queryContractNumberByLike(queryString);
    }

    @Override
    public List<StReturnValue> queryReturnValue(StReturnValue returnValue) {
        return ContractMapper.queryReturnValue(returnValue.getContractCode());
    }

    @Override
    public List<Contract> ContractList(ContractSearchCriteria ContractSearchCriteria) {
        return ContractMapper.selectContractList(ContractSearchCriteria);
    }


    @Override
    public String importCustomer(List<Contract> contractList, boolean updateSupport, String operName) {
        if (StringUtils.isNull(contractList) || contractList.size() == 0) {
            throw new ServiceException("导入合同数据不能为空！");
        }
        int successNum = 0;
        int failureNum = 0;
        StringBuilder successMsg = new StringBuilder();
        StringBuilder failureMsg = new StringBuilder();
        for (Contract contract : contractList) {
            try {
                // 验证是否存在这个用户
                Contract c = ContractMapper.selectContractByCode(contract.getContractCode());
                if (StringUtils.isNull(c)) {
                    System.out.println("导入合同：" + contract.getContractCode());
                    BeanValidators.validateWithException(validator, contract);
                    ContractMapper.insertContract(contract);
                    successNum++;
                    successMsg.append("<br/>" + successNum + "合同 " + contract.getContractCode() + " 导入成功");
                } else if (updateSupport) {
                    BeanValidators.validateWithException(validator, contract);
                    ContractMapper.updateContractByCode(contract);
                    successNum++;
                    successMsg.append("<br/>" + successNum + "、合同 " + contract.getContractCode() + " 更新成功");
                } else {
                    failureNum++;
                    failureMsg.append("<br/>" + failureNum + "、合同 " + contract.getContractCode() + " 已存在");
                }
            } catch (Exception e) {
                failureNum++;
                String msg = "<br/>" + failureNum + "、合同 " + contract.getContractCode() + " 导入失败：";
                failureMsg.append(msg + e.getMessage());
                log.error(msg, e);
            }
        }
        if (failureNum > 0) {
            failureMsg.insert(0, "很抱歉，导入失败！共 " + failureNum + " 条数据格式不正确，错误如下：");
            throw new ServiceException(failureMsg.toString());
        } else {
            successMsg.insert(0, "恭喜您，数据已全部导入成功！共 " + successNum + " 条，数据如下：");
        }
        return successMsg.toString();
    }

    @Override
    public int updateContractByCode(Contract contract) {
        return ContractMapper.editContractByCode(contract);
    }

    @Override
    public PaymentMsgVO queryMoth(StReturnValue returnValue) {
        PaymentMsgVO paymentMsgVO = new PaymentMsgVO();
        List<String> monthList = ContractMapper.selectMonthByContractCode(returnValue.getContractCode());//月份列表
        List<String> ActualPayList = ContractMapper.selectActualByContractCode(returnValue.getContractCode());//实际支付列表
        List<String> AgreedPayList = ContractMapper.selectAgreedByContractCode(returnValue.getContractCode());//预约支付列表
        paymentMsgVO.setMonthList(monthList);
        paymentMsgVO.setActualPaymentList(ActualPayList);
        paymentMsgVO.setAgreedPaymentList(AgreedPayList);
        return paymentMsgVO;

    }

    @Override
    public List<InvoiceForm> queryInvoiceList(String contractCode) {
        return invoiceFormMapper.selectInvoiceFormListBycontractNumber(contractCode);
    }

    @Override
    public void addContractList(Contract data) {
        data.setContractCategory("普通合同");
        if("月付".equals(data.getPaymentType())){
            data.setPaymentType("1");
        } else if ("季付".equals(data.getPaymentType())) {
            data.setPaymentType("2");
        } else if ("半年付".equals(data.getPaymentType())) {
            data.setPaymentType("3");
        } else if ("年付".equals(data.getPaymentType())) {
            data.setPaymentType("4");
        } else if ("验收后".equals(data.getPaymentType())) {
            data.setPaymentType("5");
        } else if ("其他".equals(data.getPaymentType())) {
            data.setPaymentType("6");
        }
        data.setFormType("upload");
        int i = insertContract(data);
        if (i > 0) {
            System.out.println("上传合同："+data.getContractCode()+"成功");
        }
        System.out.println(data);
    }

    @Override
    public void addReturnValueList(StReturnValue data) {
        data.setFormType("upload");
        int i = addReturnValue(data);
        if (i > 0) {
            System.out.println("上传回款："+data.getContractCode()+"成功");
        }
        System.out.println(data);
    }

    @Override
    public void addInvoiceFormList(InvoiceForm data) {
        data.setFormType("upload");
        int i =CustomerService.addInvoice(data);
        if (i > 0) {
            System.out.println("上传发票："+data.getContractNumber()+"成功");
        }
        System.out.println(data);

    }



    /**
     * 计算月份差并生成从起始日期的下个月开始的月份字符串数组
     *
     * @param startDate 合同的起始日期
     * @param endDate   结束日期
     * @return 月份字符串数组
     */
    public static List<String> generateMonthsFromContract(Date startDate, Date endDate,String firstPaymentMonth) {
        List<String> monthList = new ArrayList<>();
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM");

        // 将 java.util.Date 转换为 LocalDate
        LocalDate startLocalDate = startDate.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
        LocalDate endLocalDate = endDate.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();

        // 修改：使用YearMonth处理仅包含年月的日期字符串
        YearMonth firstPaymentYM = YearMonth.parse(firstPaymentMonth, formatter);
        LocalDate firstPaymentDate = firstPaymentYM.atDay(1);


        // 修改：计算从首次回款月份到结束日期的月份数
        long totalMonths = ChronoUnit.MONTHS.between(startLocalDate, endLocalDate);

        // 修改：从首次回款月份开始生成月份
        for (int i = 0; i < totalMonths; i++) {
            LocalDate currentMonth = firstPaymentDate.plusMonths(i);
            monthList.add(currentMonth.format(formatter));
        }

        return monthList;
    }

    /**
     * 生成从起始日期开始的月份字符串数组
     *
     * @param startDate       起始日期
     * @param monthDifference 月份差
     * @return 月份字符串数组
     */
    public static List<String> generateMonthList(LocalDate startDate, long monthDifference) {
        List<String> monthList = new ArrayList<>();
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM");

        // 从下个月开始生成
        for (int i = 1; i <= monthDifference; i++) {
            LocalDate currentMonth = startDate.plusMonths(i);
            monthList.add(currentMonth.format(formatter));
        }

        return monthList;
    }

    // 计算两个日期之间的月份差值
    public static long calculateMonthDifference(Date startDate, Date endDate) {
        // 将 java.util.Date 转换为 LocalDate
        LocalDate startLocalDate = startDate.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
        LocalDate endLocalDate = endDate.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();

        // 计算年份和月份的差值
        long yearDifference = endLocalDate.getYear() - startLocalDate.getYear();
        long monthDifference = endLocalDate.getMonthValue() - startLocalDate.getMonthValue();

        // 总月份差值 = 年份差值 * 12 + 月份差值
        return yearDifference * 12 + monthDifference;
    }

    /**
     * 检查当前月份是否在 paymentMsgList 的 current_month 集合中
     * @param paymentMsgList 包含 PaymentMsg 对象的列表
     * @param currentMonth 当前月份
     * @return 如果当前月份在集合中则返回 true，否则返回 false
     */
    private boolean isCurrentMonthValid(List<PaymentMsg> paymentMsgList, String currentMonth) {
        for (PaymentMsg paymentMsg : paymentMsgList) {
            if (currentMonth.equals(paymentMsg.getCurrentMonth())) {
                return true; // 当前月份在集合中
            }
        }
        return false; // 当前月份不在集合中
    }

}
